#pragma once

#include <map>
#include <stdio.h>
#include <string>

namespace zrpc {
class Buffer;

class HttpResponse {
 public:
  enum HttpStatusCode {
    kUnknown,
    k200k = 200,
    k301MovedPermanently = 301,
    k400BadRequest = 400,
    k404NotFound = 404,
  };

  explicit HttpResponse() : status_code_(kUnknown), close_connection_(false) {}

  void SetStatusCode(const char *start, const char *end_) {
    char *end = const_cast<char *>(end_);
    int64_t code = strtoll(start, &end, 10);
    SetStatusCode(HttpStatusCode(code));
  }

  void SetStatusMessage(const char *start, const char *end) {
    status_message_.assign(start, end);
  }

  HttpStatusCode GetStatusCode() { return status_code_; }
  void SetStatusCode(HttpStatusCode code) { status_code_ = code; }

  void SetStatusMessage(const std::string &message) {
    status_message_ = message;
  }

  void SetCloseConnection(bool on) { close_connection_ = on; }
  bool GetCloseConnection() { return close_connection_; }

  void SetContentType(const std::string &contentType) {
    AddHeader("Content-Type", contentType);
  }

  void AddHeader(const char *start, const char *colon, const char *end) {
    std::string field(start, colon);
    ++colon;
    while (colon < end && isspace(*colon)) {
      ++colon;
    }

    std::string value(colon, end);
    while (!value.empty() && isspace(value[value.size() - 1])) {
      value.resize(value.size() - 1);
    }
    headers_[field] = value;
  }

  void AddHeader(const std::string &key, const std::string &value) {
    headers_[key] = value;
  }

  void SetBody(const std::string &body) { body_ = body; }
  std::string GetBody() const { return body_; }
  void AppendToBuffer(Buffer *output) const;
  int32_t GetBodySize() {
    auto it = headers_.find("Content-Length");
    if (it == headers_.end()) {
      return -1;
    }

    int32_t len = atol(it->second.c_str());
    return len;
  }

 private:
  std::map<std::string, std::string> headers_;
  HttpStatusCode status_code_;
  std::string status_message_;
  bool close_connection_;
  std::string body_;
};
}  // namespace zrpc